package zy.blue7.gui.chat;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: blue7
 * @Date: 2022/2/24 20:34
 * @Version 1.0
 * @Description
 */
public class ChatServer {
    private JButton serverButton;
    private JPanel root;
    private JTextArea clientMessage;
    private JButton button1;

    public List<Channel> channels = new ArrayList<>();
    public List<ChannelHandlerContext> channelHandlerContexts = new ArrayList<>();


    public ChatServer() {

        serverButton.addActionListener(e -> {
            this.start();
            System.out.println("-----");
        });
        button1.addActionListener(e -> {
            channels.get(0).writeAndFlush("wwwwwwww");
        });
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("ChatServer");
        frame.setContentPane(new ChatServer().root);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 400);
        frame.setLocation(400, 200);
        frame.setVisible(true);
    }


    public void start() {

        //todo 1。启动器，负责组装 netty 组件 ，启动服务器
        new ServerBootstrap()
                //todo 2. BossGroup WOrkEventLoop(selector,thread)
                .group(new NioEventLoopGroup())
                //3 选择 服务器的 ServerSocketChannel 实现
                .channel(NioServerSocketChannel.class)
                //4。 boss负责处理链接，worker（child） 负责处理读写，决定力worker能执行哪些读写操作
                .childHandler(
                        // channel  代表和客户端进行数据读写通道    Initializer 初始化，   负责添加其他的handler
                        new ChannelInitializer<NioSocketChannel>() {
                            @Override
                            protected void initChannel(NioSocketChannel ch) throws Exception {

                                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                                    @Override
                                    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                                        channels.remove(ctx.channel());
                                        channelHandlerContexts.remove(ctx);
                                    }

                                    @Override
                                    public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                        channelHandlerContexts.add(ctx);
                                        channels.add(ctx.channel());
                                    }
                                });
                                // 6. 添加具体的handler
//                                ch.pipeline().addLast(new StringDecoder());//todo 将bytebuf转换成string
                                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { // TODO: 2021/9/12 自定义handler
                                    @Override  // TODO: 2021/9/12 读事件
                                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

                                        String text = clientMessage.getText();
                                        if (null != text && !text.trim().equalsIgnoreCase(""))
                                            clientMessage.setText(text + "\r\n" + ((ByteBuf)msg).toString(CharsetUtil.UTF_8));
                                        else clientMessage.setText(((ByteBuf)msg).toString(CharsetUtil.UTF_8));

//                                        channels.forEach(channel -> channel.writeAndFlush(msg+""));
                                        channelHandlerContexts.forEach(channelHandlerContext -> channelHandlerContext.writeAndFlush(msg));
                                    }
                                });
//                                ch.pipeline().addLast(new StringEncoder());
                            }

                        })
                .bind(8080);
    }
}
